import { InputManager } from './currency.manager';

export class InputService {
  //
  private inputManager: InputManager;

  /**
   *
   * @param htmlInputElement  当前input的html原生节点对象
   * @param options   组件的配置
   */
  constructor(private htmlInputElement: any, private options: any) {
    this.inputManager = new InputManager(htmlInputElement);
  }

  addNumber(keyCode: string): void {
    if (!this.rawValue) {
      this.rawValue = this.applyMask(false, '0');
    }

    // const keyChar = String.fromCharCode(keyCode);
    const selectionStart = this.inputSelection.selectionStart;
    const selectionEnd = this.inputSelection.selectionEnd;
    this.rawValue = this.rawValue.substring(0, selectionStart) + keyCode + this.rawValue.substring(selectionEnd, this.rawValue.length);
    this.updateFieldValue(selectionStart + 1);
  }

  /**
   * 删除值
   * @param keyCode
   */
  removeNumber(keyCode: string): void {
    const { decimal, thousands } = this.options;
    let selectionEnd = this.inputSelection.selectionEnd;
    let selectionStart = this.inputSelection.selectionStart;

    if (selectionStart > this.rawValue.length - this.options.suffix.length) {
      selectionEnd = this.rawValue.length - this.options.suffix.length;
      selectionStart = this.rawValue.length - this.options.suffix.length;
    }

    // there is no selection
    if (selectionEnd === selectionStart) {
      // delete key and the target digit is a number
      if (keyCode === 'Delete' && /^\d+$/.test(this.rawValue.substring(selectionStart, selectionEnd + 1))) {
        selectionEnd = selectionEnd + 1;
      }

      // delete key and the target digit is the decimal or thousands divider
      if (
        keyCode === 'Delete' &&
        (this.rawValue.substring(selectionStart, selectionEnd + 1) == decimal ||
          this.rawValue.substring(selectionStart, selectionEnd + 1) == thousands)
      ) {
        selectionEnd = selectionEnd + 2;
        selectionStart = selectionStart + 1;
      }

      // backspace key and the target digit is a number
      if (keyCode === 'Backspace' && /^\d+$/.test(this.rawValue.substring(selectionStart - 1, selectionEnd))) {
        selectionStart = selectionStart - 1;
      }

      // backspace key and the target digit is the decimal or thousands divider
      if (
        keyCode === 'Backspace' &&
        (this.rawValue.substring(selectionStart - 1, selectionEnd) === decimal ||
          this.rawValue.substring(selectionStart - 1, selectionEnd) === thousands)
      ) {
        selectionStart = selectionStart - 2;
        selectionEnd = selectionEnd - 1;
      }
    }

    this.rawValue = this.rawValue.substring(0, selectionStart) + this.rawValue.substring(selectionEnd, this.rawValue.length);
    this.updateFieldValue(selectionStart);
  }

  /**
   *  修改 value
   * @param selectionStart
   */
  updateFieldValue(selectionStart?: number): void {
    const newRawValue = this.applyMask(false, this.rawValue || '');
    selectionStart = selectionStart == null ? this.rawValue.length : selectionStart;
    this.inputManager.updateValueAndCursor(newRawValue, this.rawValue.length, selectionStart);
  }

  /**
   *  赋值
   * @param isNumber
   * @param rawValue
   * @returns {string}
   */
  applyMask(isNumber: boolean, rawValue: string): string {
    const { allowNegative, decimal, precision, prefix, suffix, thousands } = this.options;
    rawValue = isNumber ? new Number(rawValue).toFixed(precision) : rawValue;
    const onlyNumbers = rawValue.replace(/[^0-9]/g, '').replace(/[\u4e00-\u9fa5]/g, '');

    if (!onlyNumbers) {
      return '';
    }

    let integerPart = onlyNumbers
      .slice(0, onlyNumbers.length - precision)
      .replace(/^0*/g, '')
      .replace(/\B(?=(\d{3})+(?!\d))/g, thousands);

    if (integerPart === '') {
      integerPart = '0';
    }

    let newRawValue = integerPart;
    let decimalPart = onlyNumbers.slice(onlyNumbers.length - precision);

    if (precision > 0) {
      decimalPart = '0'.repeat(precision - decimalPart.length) + decimalPart;
      newRawValue += decimal + decimalPart;
    }

    // tslint:disable-next-line:radix
    const isZero = parseInt(integerPart) === 0 && (parseInt(decimalPart) === 0 || decimalPart === '');
    const operator = rawValue.indexOf('-') > -1 && allowNegative && !isZero ? '-' : '';
    return operator + prefix + newRawValue + suffix;
  }

  clearMask(rawValue: string): any {
    if (rawValue == null || rawValue === '') {
      return null;
    }
    // 去掉前缀 后缀
    let value = rawValue.replace(this.options.prefix, '').replace(this.options.suffix, '');
    // 去掉千分位
    if (this.options.thousands) {
      value = value.replace(new RegExp('\\' + this.options.thousands, 'g'), '');
    }
    // 加入小数
    if (this.options.decimal) {
      value = value.replace(this.options.decimal, '.');
    }
    // 格式化成数字
    return parseFloat(value);
  }

  get canInputMoreNumbers(): boolean {
    return this.inputManager.canInputMoreNumbers;
  }

  /**
   *  获取当前input 内容的起始与结束位置
   * @returns {any}
   */
  get inputSelection(): any {
    return this.inputManager.inputSelection;
  }

  get rawValue(): string {
    return this.inputManager.rawValue;
  }

  set rawValue(value: string) {
    this.inputManager.rawValue = value;
  }

  get value(): number {
    return this.clearMask(this.rawValue);
  }

  set value(value: number) {
    this.rawValue = this.applyMask(true, '' + value);
  }
}
